package com.sea.base.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.CallSuper
import androidx.fragment.app.Fragment
import androidx.fragment.app.InternalBasicFragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.viewbinding.ViewBinding
import com.sea.base.ext.obs.observeOnce
import com.sea.base.ui.IUIContext
import com.sea.base.utils.ViewBindingHelper
import com.sea.base.utils.param.ParamsUtils

/**
 * 基类Fragment的kotlin版
 *  显隐简化为：首次显示，显示，隐藏。
 *  @param T 见[vb]，如果真的不想使用，可以直接写[ViewBinding]（此时不能使用[vb]）
 */
abstract class BaseKtFragment<T : ViewBinding> : InternalBasicFragment(),
    com.sea.base.fragment.FragmentVisibilityChild,
    IUIContext {

    private var _vb: T? = null
    protected val vb get() = _vb ?: throw IllegalStateException("请不要在super.onCreate前调用或者没有正确的泛型T")

    private var neverVisibleBefore = true

    private var _isVisibleActivity = false
    override val isVisibleActivity get() = _isVisibleActivity

    override val isVisibleParent: Boolean get() = isAdded && (if (isFragmentManager()) !isFmHidden else isVpVisible)

    /**
     * fm 的 hide 跟 show 的回调，第一次不会调用
     */
    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        checkVisibleChangeState(!hidden)
    }

    /**
     * viewPager的可见回调，在onCreate前，[setUserVisibleHint]太乱不适合锚点
     */
    override fun setMenuVisibility(menuVisible: Boolean) {
        super.setMenuVisibility(menuVisible)
        if (isFirstResumed) {
            checkVisibleChangeState(menuVisible)
        }
    }

    /** isVisible=$isVisible userVis=$userVisibleHint isAdded=$isAdded
     * isHidden=$isHidden
     * 在嵌套fragment 中，作为 child fragment 在被重建时 以上全部为true
     * 所以真实的状态需要参考父 fragment 是否可见
     **/
    @CallSuper
    protected open fun checkVisibleChangeState(changedVisibleState: Boolean) {
        //支持子fragment 完全跟随 父fragment 可见状态
        val realVisible = changedVisibleState && isAdded && parentIsVisible()
        //区分重复状态 与 用户可见性
        if (realVisible != _isVisibleActivity) {
            _isVisibleActivity = realVisible
            when (realVisible) {
                true -> {
                    onVisible(neverVisibleBefore)
                    neverVisibleBefore = false
                }

                false -> onHidden()
            }
        }
        //每次的parentFragment的变化都需要通知 childFragment
        childFragmentManager.fragments.forEach {
            when (it) {
                is com.sea.base.fragment.FragmentVisibilityChild -> {
                    it.onParentVisibleChanged(realVisible)
                }
            }
        }
    }

    override fun onParentVisibleChanged(parentIsVisible: Boolean) {
        //内部判断过了暂时不需要isParentVisible参数
        checkVisibleChangeState(
            if (isFragmentManager()) !isFmHidden else isVpVisible
        )
    }

    /**
     * parentFragment 也必须是[FragmentVisibilityChild] 才完全有效
     * 如果不是则只判断 isAdded
     * @return parentFragment是否可见
     *
     */
    protected fun parentIsVisible(): Boolean {
        return when (val pf: Fragment? = parentFragment) {
            null -> true
            is com.sea.base.fragment.FragmentVisibilityChild -> {
                pf.isVisibleActivity
            }

            else -> {
                pf.isAdded
            }
        }
    }

    override fun onResume() {
        super.onResume()
        checkVisibleChangeState(if (isFragmentManager()) !isFmHidden else isVpVisible)
    }

    override fun onPause() {
        super.onPause()
        if (isVisibleActivity) {
            checkVisibleChangeState(false)
        }
    }

    override fun onClearVisibleState() {
        super.onClearVisibleState()
        _isVisibleActivity = false
        neverVisibleBefore = true
    }

    /**
     * @param savedInstanceState
     * 注意：由于多嵌套在内部销毁重建时（实现了saveState的，示例：ViewPager套ViewPager），也可能会引起ui错乱
     * 此处不可类比Activity强制返null，遂暂未解决，见ViewPager2的FragmentStateAdapter.restoreState
     */
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (openAutoBindParams()) {
            ParamsUtils.initWithFragment(this)
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val vbClass = ViewBindingHelper.getViewBindingClass<T>(javaClass) ?: throw IllegalArgumentException("没有找到类${this}的ViewBinding，请检查")
        if (vbClass != ViewBinding::class.java) {
            _vb = ViewBindingHelper.getViewBindingInstance(this, layoutInflater, container)
        }
        return _vb?.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        init(savedInstanceState)
        bindData()
    }

    /**
     * 是否开启参数自动绑定
     */
    protected open fun openAutoBindParams(): Boolean = true

    /**
     * 建议：
     * 1.view初始化,比如是否开启下拉刷新
     * 2.初始数据加载执
     */
    abstract fun init(savedInstanceState: Bundle?)

    /**
     * 建议：
     * 订阅viewModel的数据并进行绑定
     */
    protected abstract fun bindData()


    /////////////////////////////////////////////////////////////////////////////////////////////////
    // IUIContext的实现
    /////////////////////////////////////////////////////////////////////////////////////////////////

    override val isFinished get() = !isAdded
    override val currentFragmentManager get() = childFragmentManager
    override val rootView get() = view
    override val realDelegate get() = this

    override fun requireViewLifecycle() = viewLifecycleOwner.lifecycle

    override fun viewLifecycleWithCallback(run: (Lifecycle?) -> Unit) {
        viewLifecycleOwnerLiveData.observeOnce(this) { owner: LifecycleOwner? ->
            run.invoke(owner?.lifecycle)
        }
    }
}
